package org.example.platform.elasticsearch.service;

import cn.hutool.core.text.CharSequenceUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.script.Script;
import org.example.platform.elasticsearch.entity.HotelDocRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ESUpdateDocService {
    @Autowired
    private RestHighLevelClient client;
    public Map<String, Object> singleUpsert(String indexName, String docIdKey, Map<String, Object> recordMap) throws Exception {
        String docId = recordMap.get(docIdKey).toString();
        //将ID字段从map中移除，这步可有可无
        recordMap.remove(docIdKey);
        UpdateRequest updateRequest = new UpdateRequest(indexName, docId);
        //如果有则进行修改，没有该文档则插入，可以支持链式编程
        updateRequest.doc(recordMap).upsert(recordMap);
        try {
            UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
            HashMap<String, Object> resultMap = new HashMap<>();
            String id = updateResponse.getId(); //文档ID
            String index = updateResponse.getIndex(); //索引名称
            long version = updateResponse.getVersion(); //文档版本
            resultMap.put("id", id);
            resultMap.put("index", index);
            resultMap.put("version", version);
            return resultMap;
        } catch (IOException e) {
            log.warn(e.getMessage());
            throw new Exception("搜索错误，原因:" + e.getMessage());
        }
    }

    /**
     * 批量更新
     * @param hotelDocRequest
     * @return
     */
    public String bulkUpdate(HotelDocRequest hotelDocRequest) throws Exception {
        String indexName = hotelDocRequest.getIndexName();
        if(CharSequenceUtil.isBlank(indexName)){
            throw new Exception("索引名不能为空");
        }
        BulkRequest bulkRequest = new BulkRequest(indexName);
        List<Map<String,Object>> list = hotelDocRequest.getRecordMapList();
        for(Map<String,Object> dataMap: list){
            // 这个docIdKey代表map中值为docId对应的键值
            String docIdKey = hotelDocRequest.getDocIdKey();
            String docId = dataMap.get(docIdKey).toString();
             UpdateRequest updateRequest = new UpdateRequest(indexName,docId).doc(dataMap).upsert(dataMap);
             bulkRequest.add(updateRequest);
        }
        BulkResponse bulkResponse;
        try{
            bulkResponse = client.bulk(bulkRequest,RequestOptions.DEFAULT);
            if(bulkResponse.hasFailures()){
                return "失败，原因："+bulkResponse.buildFailureMessage();
            }else{
                return "成功";
            }
        }catch (Exception e){
            throw new Exception("搜索错误");
        }
    }

    /**
     * 根据条件更新
     * @param indexName
     * @param oldCity
     * @param newPrice
     * @return
     */
    public String updatePriceByCity(String indexName, String oldCity, String newPrice) {
        UpdateByQueryRequest update = new UpdateByQueryRequest(indexName);
        // 按照城市查询文档的query
        update.setQuery(new TermQueryBuilder("city",oldCity));
        update.setScript(new Script("ctx._source['price']='"+newPrice+"';"));
        try {
            BulkByScrollResponse response = client.updateByQuery(update,RequestOptions.DEFAULT);
            return response.toString();
        } catch (IOException e) {
            throw new RuntimeException(e+"按照条件修改错误");
        }
    }
}
